#pragma once

#include <iostream>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <cassert>
#include <sys/stat.h>
#include <fcntl.h>
#include "Log.hpp"

using namespace std; // 实际项目中 不展开

#define PATH_NAME "/home/lhr/linux" // 此路径一定要有访问权限
#define PROJ_ID 0x66                // 0~255
#define SHM_SIZE 4096               // 共享内存的大小 最好是页(PAGE: 4096)的整数倍 4kb
#define FIFO_NAME "./fifo"          // 当前路径下创建一个fifo管道文件

string ConvertToHex(key_t k)
{
    char buffer[32];
    snprintf(buffer, sizeof buffer, "0x%x", k);
    return buffer;
}

class Init
{
public:
    Init()
    {
        umask(0);
        int n = mkfifo(FIFO_NAME, 0666);
        assert(n == 0);
        (void)n;
        Log("create fifo success", Notice) << std::endl;
    }
    ~Init()
    {
        unlink(FIFO_NAME);
        Log("remove fifo success", Notice) << std::endl;
    }
};

#define READ O_RDONLY
#define WRITE O_WRONLY

int OpenFIFO(std::string pathname, int flags)
{
    int fd = open(pathname.c_str(), flags);
    assert(fd >= 0);
    return fd;
}

//服务端调用read去阻塞等待数据 直到有人向管道写数据 等待停止
void Wait(int fd)
{//no_use仅仅是实现“读数据”这一动作的对象 其中的数据无意义
    Log("等待中....", Notice) << std::endl;
    //read接口从fd读存到tmp 无数据则阻塞等待
    uint32_t no_use = 0;
    ssize_t s = read(fd, &no_use, sizeof(uint32_t));
    assert(s == sizeof(uint32_t));
    (void)s;
}

//客户端调用write向管道写数据 此动作使得管道中添加数据 服务端停止等待
void Wake(int fd)
{//no_use仅仅是实现“写数据”这一动作的对象 其中的数据无意义
    uint32_t no_use = 1;
    ssize_t s = write(fd, &no_use, sizeof(uint32_t));
    assert(s == sizeof(uint32_t));
    (void)s;
    Log("唤醒中....", Notice) << std::endl;
}

void CloseFifo(int fd)
{
    close(fd);
}